package de.mrapp.tabswitcher.util;

import ohos.agp.colors.RgbColor;
import ohos.agp.components.Component;
import ohos.agp.components.element.ShapeElement;
import ohos.agp.render.Arc;
import ohos.agp.render.Canvas;
import ohos.agp.render.Paint;
import ohos.agp.render.Path;
import ohos.agp.utils.Color;
import ohos.agp.utils.Point;
import ohos.agp.utils.RectFloat;


public class ViewUtils {
    private static boolean enableBorderRadius = true;

    public static void setEnableBorderRadius(boolean enableBorderRadius) {
        ViewUtils.enableBorderRadius = enableBorderRadius;
    }

    private static RectFloat oval = new RectFloat();
    private static Path ovalPath = new Path();

    private static Path sPath = new Path();

    private static Paint sBorderPaint;

    private static Paint sBackgroundPaint;

    public static void drawBorder(Canvas canvas, int borderColor, int width, int height, int borderWidth,
                                  int borderTopLeftRadius, int borderTopRightRadius, int borderBottomLeftRadius, int borderBottomRightRadius) {

        if (canvas == null || borderWidth <= 0 || borderColor == Color.TRANSPARENT.getValue()) {
            return;
        }
        if (sBorderPaint == null) {
            Paint  paint = new Paint();
            paint.setAntiAlias(true);
            paint.setStyle(Paint.Style.STROKE_STYLE);
            sBorderPaint = paint;
        }
        sBorderPaint.setColor(new Color(borderColor));

        sBorderPaint.setStrokeWidth(borderWidth);
        if (!enableBorderRadius) {
            borderTopLeftRadius = 0;
            borderTopRightRadius = 0;
            borderBottomLeftRadius = 0;
            borderBottomRightRadius = 0;
        }
        float halfBorderWidth = (borderWidth / 2.0f);
        canvas.drawLine(new Point(halfBorderWidth, borderTopLeftRadius > 0 ? (float) ((double) borderTopLeftRadius + halfBorderWidth) : 0), new Point(halfBorderWidth,
                borderBottomLeftRadius > 0 ? (float) ((double) height - borderBottomLeftRadius - halfBorderWidth) : height), sBorderPaint);
        //        //draw top border
        canvas.drawLine(new Point(borderTopLeftRadius > 0 ? (float) ((double) halfBorderWidth + borderTopLeftRadius) : 0, halfBorderWidth), new Point(
                borderTopRightRadius > 0 ? (float) ((double) width - borderTopRightRadius - halfBorderWidth) : width, halfBorderWidth), sBorderPaint);
        //        //draw right border
        canvas.drawLine(new Point((float) ((double)width - halfBorderWidth), borderTopRightRadius > 0 ? (float) ((double) halfBorderWidth + borderTopRightRadius) : 0), new Point((float) ((double)width - halfBorderWidth),
                borderBottomRightRadius > 0 ? (float) ((double) height - borderBottomRightRadius - halfBorderWidth) : height), sBorderPaint);
        //draw bottom border
        canvas.drawLine(new Point(borderBottomLeftRadius > 0 ? (float) ((double) halfBorderWidth + borderBottomLeftRadius) : 0, (float) ((double)height - halfBorderWidth)),
                new Point(borderBottomRightRadius > 0 ? (float) ((double) width - borderBottomRightRadius - halfBorderWidth) : width, (float) ((double)height - halfBorderWidth)), sBorderPaint);

        //draw top left corner
        if (borderTopLeftRadius > 0) {
            oval.clear();
            ovalPath.reset();
            oval.fuse(0, 0, 2 * borderTopLeftRadius, 2 * borderTopLeftRadius);
            ovalPath.addArc(oval, 179, 91);
            ovalPath.offset(halfBorderWidth, halfBorderWidth);
            canvas.drawPath(ovalPath, sBorderPaint);
        }

        //draw top right corner
        if (borderTopRightRadius > 0) {
            oval.clear();
            ovalPath.reset();
            oval.fuse(width - 2 * borderTopRightRadius, 0, width, 2 * borderTopRightRadius);
            ovalPath.addArc(oval, 269, 91);
            ovalPath.offset(-halfBorderWidth, halfBorderWidth);
            canvas.drawPath(ovalPath, sBorderPaint);

        }

        //draw bottom right corner
        if (borderBottomRightRadius > 0) {
            oval.clear();
            ovalPath.reset();
            oval.fuse(width - 2 * borderBottomRightRadius, height - 2 * borderBottomRightRadius, width, height);
            ovalPath.addArc(oval, -1, 91);
            ovalPath.offset(-halfBorderWidth, -halfBorderWidth);
            canvas.drawPath(ovalPath, sBorderPaint);
        }

        //draw bottom left corner
        if (borderBottomLeftRadius > 0) {
            oval.clear();
            ovalPath.reset();
            oval.fuse(0, height - 2 * borderBottomLeftRadius, 2 * borderBottomLeftRadius, height);
            ovalPath.addArc(oval, 89, 91);
            ovalPath.offset(halfBorderWidth, -halfBorderWidth);
            canvas.drawPath(ovalPath, sBorderPaint);

        }
    }

    public static void drawBackground(Canvas canvas, int backgruondColor, int width, int height, int borderWidth,
                                      int borderTopLeftRadius, int borderTopRightRadius, int borderBottomLeftRadius, int borderBottomRightRadius) {
        if (canvas == null) {
            return;
        }
        if (null == sBackgroundPaint) {
            sBackgroundPaint = new Paint();
            sBackgroundPaint.setAntiAlias(true);
        }

        sBackgroundPaint.setColor(new Color(backgruondColor));
        if (!enableBorderRadius) {
            borderTopLeftRadius = 0;
            borderTopRightRadius = 0;
            borderBottomLeftRadius = 0;
            borderBottomRightRadius = 0;
        }
        sPath.reset();
        //start point
        sPath.moveTo(borderWidth + (borderTopLeftRadius > 0 ? borderTopLeftRadius : 0), borderWidth);
        //line top edge
        sPath.lineTo(width - borderWidth - (borderTopRightRadius > 0 ? borderTopRightRadius : 0), borderWidth);
        //arc to right edge
        if (borderTopRightRadius > 0) {
            oval.clear();
            oval.fuse(width - 2 * borderTopRightRadius, 0, width, 2 * borderTopRightRadius);
            // sPath.offset(-halfBorderWidth, halfBorderWidth);
            sPath.arcTo(oval, 270, 90);
        }
        //line right edge
        sPath.lineTo(width - borderWidth, height - borderWidth - (borderBottomRightRadius > 0 ? borderBottomRightRadius : 0));
        //arc to bottom edge
        if (borderBottomRightRadius > 0) {

            oval.clear();
            oval.fuse(width - 2 * borderBottomRightRadius, height - 2 * borderBottomRightRadius, width, height);
            // sPath.offset(-halfBorderWidth, -halfBorderWidth);
            sPath.arcTo(oval, 0, 90);
        }
        //line bottom edge
        sPath.lineTo(borderWidth + (borderBottomLeftRadius > 0 ? borderBottomLeftRadius : 0), height - borderWidth);
        //arc to left edge
        if (borderBottomLeftRadius > 0) {
            oval.clear();
            oval.fuse(0, height - 2 * borderBottomLeftRadius, 2 * borderBottomLeftRadius, height);
            //   sPath.offset(halfBorderWidth, -halfBorderWidth);
            sPath.arcTo(oval, 90, 90);
        }
        //line left edge
        sPath.lineTo(borderWidth, borderWidth + (borderTopLeftRadius > 0 ? borderTopLeftRadius : 0));
        //arc to top edge
        if (borderTopLeftRadius > 0) {
            oval.clear();
            oval.fuse(0, 0, 2 * borderTopLeftRadius, 2 * borderTopLeftRadius);
            // sPath.offset(halfBorderWidth, halfBorderWidth);
            sPath.arcTo(oval, 180, 90);
        }
        canvas.drawPath(sPath, sBackgroundPaint);
    }

    public static void clipCanvas(Canvas canvas, int width, int height, int borderWidth,
                                  int borderTopLeftRadius, int borderTopRightRadius, int borderBottomLeftRadius, int borderBottomRightRadius) {
        clipCanvas(null, canvas, width, height, borderWidth, borderTopLeftRadius, borderTopRightRadius, borderBottomLeftRadius, borderBottomRightRadius);
    }

    public static void clipCanvas(Component view, Canvas canvas, int width, int height, int borderWidth,
                                  int borderTopLeftRadius, int borderTopRightRadius, int borderBottomLeftRadius, int borderBottomRightRadius) {
        if (canvas == null) {
            return;
        }

        if (!enableBorderRadius) {
            borderTopLeftRadius = 0;
            borderTopRightRadius = 0;
            borderBottomLeftRadius = 0;
            borderBottomRightRadius = 0;
        }

        if (!isRounded(borderTopLeftRadius, borderTopRightRadius, borderBottomLeftRadius, borderBottomRightRadius)) {
            return;
        }
        sPath.reset();
        //start point
        sPath.moveTo((borderTopLeftRadius > 0 ? borderTopLeftRadius : 0), 0);
        //line top edge
        sPath.lineTo(width - (borderTopRightRadius > 0 ? borderTopRightRadius : 0), 0);
        //arc to right edge
        if (borderTopRightRadius > 0) {
//            oval.set(width - 2 * borderTopRightRadius, 0, width, 2 * borderTopRightRadius);
            oval.clear();
            oval.fuse(width - 2 * borderTopRightRadius, 0, width, 2 * borderTopRightRadius);
            sPath.arcTo(oval, 270, 90);
        }
        //line right edge
        sPath.lineTo(width, height - (borderBottomRightRadius > 0 ? borderBottomRightRadius : 0));
        //arc to bottom edge
        if (borderBottomRightRadius > 0) {
//            oval.set(width - 2 * borderBottomRightRadius, height - 2 * borderBottomRightRadius, width, height);
            oval.clear();
            oval.fuse(width - 2 * borderBottomRightRadius, height - 2 * borderBottomRightRadius, width, height);
            sPath.arcTo(oval, 0, 90);
        }
        //line bottom edge
        sPath.lineTo((borderBottomLeftRadius > 0 ? borderBottomLeftRadius : 0), height);
        //arc to left edge
        if (borderBottomLeftRadius > 0) {
//            oval.set(0, height - 2 * borderBottomLeftRadius, 2 * borderBottomLeftRadius, height);
            oval.clear();
            oval.fuse(0, height - 2 * borderBottomLeftRadius, 2 * borderBottomLeftRadius, height);
            sPath.arcTo(oval, 90, 90);
        }
        //line left edge
        sPath.lineTo(0, (borderTopLeftRadius > 0 ? borderTopLeftRadius : 0));
        //arc to top edge
        if (borderTopLeftRadius > 0) {
//            oval.set(0, 0, 2 * borderTopLeftRadius, 2 * borderTopLeftRadius);
            oval.clear();
            oval.fuse(0, 0, 2 * borderTopLeftRadius, 2 * borderTopLeftRadius);
            sPath.arcTo(oval, 180, 90);
        }
        canvas.clipPath(sPath, Canvas.ClipOp.DIFFERENCE);
    }

    private static boolean isRounded(int borderTopLeftRadius, int borderTopRightRadius, int borderBottomLeftRadius,
                                     int borderBottomRightRadius) {
        return borderTopLeftRadius > 0 || borderTopRightRadius > 0 || borderBottomLeftRadius > 0
                || borderBottomRightRadius > 0;
    }

    public static void drawBackgroundAndBorder(Component component, int backgruondColor,
                                               int borderColor, int borderWidth,
                                               int borderTopLeftRadius, int borderTopRightRadius,
                                               int borderBottomLeftRadius, int borderBottomRightRadius) {
        ShapeElement shapeElement = new ShapeElement();
        float[] radii = new float[]{borderTopLeftRadius, borderTopLeftRadius,
                borderTopRightRadius, borderTopRightRadius,
                borderBottomLeftRadius, borderBottomLeftRadius,
                borderBottomRightRadius, borderBottomRightRadius};
        shapeElement.setCornerRadiiArray(radii);
        if (borderWidth > 0) {
            shapeElement.setStroke(borderWidth, RgbColor.fromArgbInt(borderColor));
        }
        shapeElement.setRgbColor(RgbColor.fromArgbInt(backgruondColor));
        component.setBackground(shapeElement);

    }
}
